
package com.rykj.qxj.monitor.quartz;

import com.rykj.qxj.server.dao.TaskMapper;
import lombok.extern.log4j.Log4j;
import org.quartz.*;
import org.quartz.impl.StdSchedulerFactory;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.util.List;
import java.util.Map;

import static org.quartz.JobBuilder.newJob;

@Component
@Log4j
public class QuartzManager {

    private static SchedulerFactory gSchedulerFactory = new StdSchedulerFactory();
    @Resource
    private TaskMapper taskMapper;
    @PostConstruct
    public void init(){
        List<Map<String,Object>> tasks = taskMapper.getAllNormalTasks();
        if(!CollectionUtils.isEmpty(tasks)){
            for (Map<String,Object> taskMap:tasks) {
                String taskStatus = (String) taskMap.get("taskStatus");
                String taskName = (String) taskMap.get("taskName");
                String executeRate = (String) taskMap.get("executeRate");
                Integer taskId = (Integer) taskMap.get("taskId");
                try {
                    addJob(taskName,taskId,executeRate);
                    //如果是禁用的任务改禁用
                    if("disable".equals(taskStatus)){
                        shutdownJob(taskName);
                    }
                }catch (Exception e){
                   log.error("=====任务==="+taskName+"====执行频率====="+executeRate+"======载入Quartz容器异常",e);
                }
            }
        }
    }
    /**
     * 添加一个定时任务，使用默认的任务组名，触发器名，触发器组名
     *
     * @param jobName
     *            任务名
     *            任务
     * @param time
     *            时间设置，参考quartz说明文档
     * @throws SchedulerException
     */
    public static void addJob(String jobName,Integer taskId,String time) {
        log.info("=====添加任务===="+jobName);
        try {
            Scheduler sched = gSchedulerFactory.getScheduler();
            // 1. 创建一个JodDetail实例 将该实例与FieldTaskJob.class绑定 (链式写法)
            JobDetail jobDetail = newJob(FieldTaskJob.class) // 定义Job类为FieldTaskJob类，这是真正的执行逻辑所在
                    .withIdentity(jobName) // 定义name/group
                    .usingJobData("taskId",taskId)
                    .build();
            // 触发器
            Trigger trigger=TriggerBuilder.newTrigger().withIdentity(jobName+"Trigger", jobName+"TriggerGroup")
                    .withSchedule(CronScheduleBuilder.cronSchedule(time))
                    .startNow().build();
            sched.scheduleJob(jobDetail, trigger);
            // 启动
            if (!sched.isShutdown()){
                sched.start();
                log.info("=====启动任务===="+jobName);
            }
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException(e);
        }
    }

    /**
     * 修改一个任务的触发时间(使用默认的任务组名，触发器名，触发器组名)
     *
     * @param jobName
     * @param time
     */
    public static void modifyJobTime(String jobName,Integer taskId, String time) {
        log.info("=====修改任务===="+jobName+"====执行时间===="+time);
        try {
            Scheduler sched = gSchedulerFactory.getScheduler();
            TriggerKey triggerKey = new TriggerKey(jobName+"Trigger",jobName+"TriggerGroup");
          //  JobKey jobKey = new JobKey(jobName,JOB_GROUP_NAME);
            CronTrigger trigger = (CronTrigger) sched.getTrigger(triggerKey);
            if(trigger != null) {
                String oldTime = trigger.getCronExpression();
                log.info("任务："+jobName+" 的oldTime为："+oldTime+"====更新时间为 time==="+time+"===比较结果=="+oldTime.equalsIgnoreCase(time));
              //   if (!oldTime.equalsIgnoreCase(time)) {
                removeJob(jobName);
               // }
            }
            addJob(jobName,taskId,time);
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException(e);
        }
    }


    /**
     * 修改一个任务的触发时间
     *
     * @param triggerName
     * @param triggerGroupName
     * @param time
     */
    public static void modifyJobTime(String triggerName,
                                     String triggerGroupName, String time) {
        try {
            Scheduler sched = gSchedulerFactory.getScheduler();
            TriggerKey triggerKey = new TriggerKey(triggerName,triggerGroupName);
            CronTrigger trigger = (CronTrigger) sched.getTrigger(triggerKey);
            if(trigger == null) {
                return;
            }
            String oldTime = trigger.getCronExpression();
            if (!oldTime.equalsIgnoreCase(time)) {
                CronTrigger ct =  trigger;
                // 修改时间
              //  ct.setCronExpression(time);
                // 重启触发器
                sched.resumeTrigger(triggerKey);
            }
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException(e);
        }
    }


    /**
     * 移除一个任务(使用默认的任务组名，触发器名，触发器组名)
     *
     * @param jobName
     */
    public static void removeJob(String jobName) {
        try {
            log.info("=====移除任务==开始===="+jobName);
            TriggerKey triggerKey = new TriggerKey(jobName+"Trigger",jobName+"TriggerGroup");
            JobKey jobKey = new JobKey(jobName);
            Scheduler sched = gSchedulerFactory.getScheduler();
            sched.pauseTrigger(triggerKey);// 停止触发器
            sched.unscheduleJob(triggerKey);// 移除触发器
            sched.deleteJob(jobKey);// 删除任务
            log.info("=====移除任务==结束=="+jobName);
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException(e);
        }
    }

    /**
     * 移除一个任务
     *
     * @param jobName
     * @param jobGroupName
     * @param triggerName
     * @param triggerGroupName
     */
    public static void removeJob(String jobName, String jobGroupName,
                                 String triggerName, String triggerGroupName) {
        try {
            TriggerKey triggerKey = new TriggerKey(triggerName,triggerGroupName);
            JobKey jobKey = new JobKey(jobName,jobGroupName);
            Scheduler sched = gSchedulerFactory.getScheduler();
            sched.pauseTrigger(triggerKey);// 停止触发器
            sched.unscheduleJob(triggerKey);// 移除触发器
            sched.deleteJob(jobKey);// 删除任务
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException(e);
        }
    }


     /**
     * 启动所有定时任务
     */
    public static void startJobs() {
        try {
            Scheduler sched = gSchedulerFactory.getScheduler();
            sched.start();
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException(e);
        }
    }


    /**
     * 关闭所有定时任务
     */
    public static void shutdownJobs() {
        try {
            Scheduler sched = gSchedulerFactory.getScheduler();
            if(!sched.isShutdown()) {
                sched.shutdown();
            }
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException(e);
        }
    }
    /**
     * 关闭定时任务
     */
    public static void shutdownJob(String jobName) {
        try {
            TriggerKey triggerKey = new TriggerKey(jobName+"Trigger",jobName+"TriggerGroup");
            Scheduler sched = gSchedulerFactory.getScheduler();
            sched.pauseTrigger(triggerKey);// 停止触发器
            sched.unscheduleJob(triggerKey);// 移除触发器
            if(!sched.isShutdown()) {
                sched.shutdown();
            }
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException(e);
        }
    }
    /**
     * 启动定时任务
     */
    public static void startJob(String jobName) {
        try {
            TriggerKey triggerKey = new TriggerKey(jobName+"Trigger",jobName+"TriggerGroup");
           // JobKey jobKey = new JobKey(jobName);
            Scheduler sched = gSchedulerFactory.getScheduler();
           // sched.pauseJob(triggerKey);
            sched.resumeTrigger(triggerKey);// 重启触发器
           // sched.unscheduleJob(triggerKey);// 移除触发器
            if(sched.isShutdown()) {
                sched.start();
            }
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException(e);
        }
    }
}

